#include "../s21_decimal.h"

void s21_copy_long(s21_long_decimal *source, s21_long_decimal *destination) {
  for (int i = 0; i <= LONG_LAST; i++) {
    destination->bits[i] = source->bits[i];
  }
}

void s21_reset_long_only_bits(s21_long_decimal *value) {
  for (int i = 0; i < LONG_LAST; i++) {
    value->bits[i] = 0;
  }
}

int s21_is_long_zero(s21_long_decimal *value) {
  int result = TRUE;

  for (int i = 0; i < LONG_LAST && result == TRUE; i++) {
    if (value->bits[i] != 0) {
      result = FALSE;
    }
  }

  return result;
}

int s21_is_not_long_zero(s21_long_decimal *value) {
  return s21_is_long_zero(value) == TRUE ? FALSE : TRUE;
}

int s21_equalize_long_scale(s21_long_decimal *first, s21_long_decimal *second) {
  int first_scale = s21_get_long_scale(first);
  int second_scale = s21_get_long_scale(second);
  int difference = first_scale - second_scale;
  s21_long_decimal *pointer = NULL;
  int delta = 0;

  if (difference > 0) {
    delta = difference;
    s21_set_long_scale(second, second_scale + delta);
    pointer = second;
  } else if (difference < 0) {
    delta = -difference;
    s21_set_long_scale(first, first_scale + delta);
    pointer = first;
  }

  for (int i = 0; i < delta; i++) {
    s21_mul_long_by_ten(pointer);
  }

  return difference;
}

int s21_shift_long_bits_to_left(s21_long_decimal *value, int shift) {
  int top_bit_index = s21_get_top_long_bit_index(value);

  if (shift == 0 || top_bit_index == -1) {
    return OK;
  } else if (shift < 0 || shift > MAX_LONG_INDEX - top_bit_index) {
    return ERROR;
  }

  s21_long_decimal value_copy = INIT_ZERO_S21_LONG_DECIMAL;
  s21_copy_long(value, &value_copy);
  s21_reset_long_only_bits(value);

  for (int i = 0; i <= top_bit_index; i++) {
    if (s21_get_long_bit(&value_copy, i) == 1) {
      s21_set_long_bit(value, i + shift);
    }
  }

  return OK;
}

int s21_shift_long_bits_to_right(s21_long_decimal *value, int shift) {
  int top_bit_index = s21_get_top_long_bit_index(value);

  if (shift == 0 || top_bit_index == -1) {
    return OK;
  } else if (shift < 0 || shift > MAX_LONG_INDEX - top_bit_index) {
    return ERROR;
  }

  s21_long_decimal value_copy = INIT_ZERO_S21_LONG_DECIMAL;
  s21_copy_long(value, &value_copy);
  s21_reset_long_only_bits(value);

  for (int i = shift; i <= top_bit_index; i++) {
    if (s21_get_long_bit(&value_copy, i) == 1) {
      s21_set_long_bit(value, i - shift);
    }
  }

  return OK;
}

int s21_compare_only_long_bits(s21_long_decimal *first,
                               s21_long_decimal *second) {
  int difference = 0;
  int first_top_bit_index = s21_get_top_long_bit_index(first);
  int second_top_bit_index = s21_get_top_long_bit_index(second);

  if (first_top_bit_index > second_top_bit_index) {
    difference = 1;
  } else if (first_top_bit_index < second_top_bit_index) {
    difference = -1;
  } else {
    for (int i = first_top_bit_index; i >= 0 && difference == 0; i--) {
      difference = s21_get_long_bit(first, i) - s21_get_long_bit(second, i);
    }
  }

  return difference;
}

int s21_get_top_long_bit_index(s21_long_decimal *value) {
  int result = -1;
  int index = MAX_LONG_INDEX;

  for (int i = LONG_LAST - 1; i >= 0 && value->bits[i] == 0; i--) {
    index -= 32;
  }

  for (; index >= 0 && result == -1; index--) {
    if (s21_get_long_bit(value, index) == 1) {
      result = index;
    }
  }

  return result;
}